#ifndef _ROLEMGR_H_
#define _ROLEMGR_H_

#include <hash_map>
#include <sdhlp\singleton.h>
#include <sdhlp\simpleobjectpool.h>
#include "ISProto.h"

namespace google
{
    namespace protobuf
    {
        class Message;
    }
}

#define MAX_SAVE_COUNT 32
#define TIMER_SAVE  30*1000

#define _CHECKROLE(X)  {\
    _CHECKROLEEXIST(##X)\
    _CHECKROLESVRID(##X)\
    _CHECKROLEINIT(##X)\
    _CHECKROLELOCK(##X)\
}

#define _CHECKROLEEXIST(X) {\
    if (NULL == ##X)\
    {\
        GIPKG_ROLEERROR_NTF stNtf;\
        stNtf.set_error(ITERR_ROLE_NOEXIST);\
        CGSHandler::Instance()->Send(dwSvrID, dwTransID, GIID_ROLEERROR_NTF, &stNtf);\
        return;\
    }\
}

#define _CHECKROLESVRID(X) {\
    if (##X->GetSvrID() != dwSvrID)\
    {\
        GIPKG_ROLEERROR_NTF stNtf;\
        stNtf.set_error(ITERR_ERR_GS);\
        CGSHandler::Instance()->Send(dwSvrID, dwTransID, GIID_ROLEERROR_NTF, &stNtf);\
        return;\
    }\
}

#define _CHECKROLEINIT(X) {\
    if (!##X->IsInit())\
    {\
        GIPKG_ROLEERROR_NTF stNtf;\
        stNtf.set_error(ITERR_ROLE_NOINIT);\
        CGSHandler::Instance()->Send(dwSvrID, dwTransID, GIID_ROLEERROR_NTF, &stNtf);\
        return;\
    }\
}

#define _CHECKROLELOCK(X) {\
    if (##X->IsLock())\
    {\
        GIPKG_ROLEERROR_NTF stNtf;\
        stNtf.set_error(ITERR_ROLE_LOCK);\
        CGSHandler::Instance()->Send(dwSvrID, dwTransID, GIID_ROLEERROR_NTF, &stNtf);\
        return;\
    }\
}

class CRole;

class CRoleMgr
{
    friend class CTradeMgr;
    friend class CMailMgr;
    friend class CItemDB;
public:
    DECLARE_SINGLETON(CRoleMgr)

    void Process();

    void ReleaseRole(CRole* poRole);

    void RoleEnter(UINT32 dwSvrID, UINT32 dwTransID, const GIPKG_ENTER_REQ* pstReq);
    void RoleLeave(UINT32 dwSvrID, UINT32 dwTransID, const GIPKG_LEAVE_REQ* pstReq);

    void ProceRoleMsg(UINT32 dwSvrID, UINT32 dwTransID, UINT16 wMsgID, ::google::protobuf::Message * pMsg);

    void SessionConnected();
    void SessionDisConnected(UINT32 dwSvrID);

    CRole* _GetRole(UINT32 dwRoleID);

protected:
    CRoleMgr();
    virtual ~CRoleMgr();

    void _AddRole(CRole* poRole);

    UINT32 GetRoleIDFromMsg(UINT16 wMsg, ::google::protobuf::Message * pMsg);

    SGDP::CSimpleObjPool<CRole> m_oRolePool;

private:
    UINT32 m_dwLastCheck;
    stdext::hash_map<UINT32, CRole*> m_mapRole;
};

#endif
